--
-- Author: shineflag
-- Date: 2017-03-21 10:04:03
--
-- 管理 useragent


local skynet = require "skynet"
local log = require "log"
local proto = require("json_proto")
local json = require("json")

local assert = assert

local TAG =  "USER_MGR"
local CLEAR_TIME = 2*3600 ---掉线后多久useragent被回收 (2hour)
local SLEEP_TIME = 60*100 -- 1min
local SNG_CANCEL = 2*60 -- 掉线后多久 会取消报名的sng的比赛

local CMD = {}   --所有的命令管理

local idle_agent = {}  --空闲的agent
local wait_agent = {}   --等待连接
local online_agent = {} --已经登陆的玩家
local clear_agent = {}  --掉线等待被清理的玩家的时间
local sng_cancel = {}   --掉线sng 取消报名的信息
local online_players = 0   --在线人数

local ustatus = {
	online = 1,       --在线
	disconnect = 2,   --掉线
}


--一个玩家是否在线
local function is_online_user(user)
	return user.status == ustatus.online 
end

local function clear_user_agent(mid)
	clear_agent[mid] = nil 
	local user = online_agent[mid]
	skynet.call(user.agent, "lua", "logout")
	online_agent[mid] = nil 
	table.insert(idle_agent, user.agent) 
	log.d(TAG, "player[%d] clear agent[%x]",mid, user.agent)
end


local function  get_uinfo(mid)
	local uinfo_center = skynet.uniqueservice "uinfo"
	local ret, data = skynet.call(uinfo_center, "lua", "getuinfo", mid) 
	if ret then 
		log.d(TAG,"load user[%d] uinfo[%s]", mid, json.encode(data))
		return data
	else
		log.e(TAG, "load user[%d] uinfo failed",mid)
		return {}
	end
end


--获取一个空闲的agent call by halld
function CMD.get_idle_agent()
	local agent
	if #idle_agent > 0 then 
		agent = table.remove(idle_agent,1)
	else
		agent = skynet.newservice "useragent"
	end

	table.insert(wait_agent,agent)
	return agent
end

--用户登录报备 call by useragent
function CMD.report_login( mid, src)
	local user =  online_agent[mid] 
	if user then 
		--user.agent = src
		if user.status ~= ustatus.online then
			online_players = online_players + 1
			user.status = ustatus.online
			log.d(TAG,"user[%d] relogin and check disconnect",mid)
		else
			log.d(TAG,"user[%d] relogin and not check disconnect",mid)
		end

		if user.agent ~= src then 
			log.e(TAG,"user[%d] relogin error agent old[%d] now[%d]",mid,user.agent, src)
		end
		clear_agent[mid] = nil 
		sng_cancel[mid] = nil
	else
		for id, agent in pairs(wait_agent) do 
			if agent == src then 
				table.remove(wait_agent,id)
				user = {agent = src,status = ustatus.online}
				break
			end
		end

		if user then 
			online_agent[mid] = user
			online_players = online_players + 1 
		else
			log.e(TAG,"user[%d] not find wait agent",mid)
		end
	end
	log.d(TAG,"user[%d] login now online[%d]", mid, online_players)
end

--用户掉线报备 call by useragent
function CMD.report_disconnect(mid, src)
	local user = online_agent[mid]
	if user then 
		assert(user.agent == src)
		user.status = ustatus.disconnect
		clear_agent[mid] = os.time() + CLEAR_TIME
		sng_cancel[mid] = os.time() + SNG_CANCEL
		log.d(TAG,"user[%d] clear time[%d]",mid,clear_agent[mid])
		online_players = online_players - 1
	else
		log.e(TAG, "user[%d] is no logined",mid)
	end
	log.d(TAG,"user[%d] logout now online[%d]", mid, online_players)
end


skynet.start(function()

	skynet.dispatch("lua",  function(session,source,cmd,...)
		--log.d(TAG,"recv cmd[%s]",cmd)
		local f = CMD[cmd]
		if f then
			if session ~= 0 then
				skynet.ret(skynet.pack(f(...)))
			else
				f( ... )
			end
		else
			log.e(TAG,"not found cmd[%s]",cmd)
		end
	end)

	skynet.fork(function()
		while true do
			update()
			skynet.sleep(SLEEP_TIME)
		end
    end)

end)